<?php
// +----------------------------------------------------------------------
// | Author: July
// +----------------------------------------------------------------------
// | 创建时间: 2023-12-27 20:39:42
// +----------------------------------------------------------------------
// | 系统配置管理控制器
// +----------------------------------------------------------------------

namespace july\julyadmin\admin\controller;

use july\julyadmin\builder\Form;
use july\julyadmin\builder\traits\HasBuilder;
use july\julyadmin\common\model\Config as ConfigModel;

class Config extends Common
{
    use HasBuilder;

    //不需要登录验证的控制器和方法，如：['index']
    protected $noNeedLogin = [];
    //不需要权限验证的控制器和方法，如：['index']
    protected $noPermissionAuth = [];

    public function __construct()
    {
        //重新初始化父类
        parent::initialize();
        //数据模型
        $this->dataModel = new ConfigModel();
        //join关联查询的表信息如，['category'=>'inner','comment'=>'left']
        $this->relationWithJoins = [];
        //with预查询关联表信息，如category,comment
        $this->relationWiths = [];
        //页面标题
        $this->pageTitle = '平台配置';
        //允许表格行内编辑的字段,如name,sex
        $this->allowRowEditField = ['config_name', 'config_key'];
        //不允许删除的主键数组，如1,2,3
        $this->noDeletePrimarykeys = [];
        //不允许编辑的主键数组，如1,2,3
        $this->noEditPrimarykeys = [];
        //不允许禁用的主键数组，如1,2,3
        $this->noDisabledPrimarykeys = [];
        //下拉join关联查询的表信息如，['category'=>'inner','comment'=>'left']
        $this->selectRelationWithJoins = [];
        //下拉with预查询关联表信息，如category,comment
        $this->selectRelationWiths = [];
        //下拉列表默认查询条件，如 [['disabled', '=', 1]]，如果有配置了$this->selectRelationWithJoins，这里就需要注意了，排序字段需要带上表名加一个点，如admin.
        $this->selectWhere = [];
        //下拉列表模糊查询字段,如 'name|title'，如果有配置了$this->selectRelationWithJoins，这里就需要注意了，排序字段需要带上表名加一个点，如admin，当前表可以不加
        $this->selectSearch = 'config_name';
        //下拉列表默认 Text 字段 如 '{id}#{nickname}'或者'id:{id}-名称:{name}'，如果有配置了$this->selectRelationWithJoins，这里就需要注意了，排序字段需要带上表名加一个点，如admin，当前表可以不加
        $this->selectTextField = '{id}#{name}';
        //下拉默认id字段,如：id
        $this->selectIdField = 'id';
        //下拉列表查询时的字段，如：id,name，如果有配置了$this->selectRelationWithJoins，这里就需要注意了，排序字段需要带上表名加一个点，如admin.，当前表可以不加
        $this->selectFields = '*';
        //下拉列表父id字段，如：parent_id，如果有配置了$this->selectRelationWithJoins，这里就需要注意了，排序字段需要带上表名加一个点，如admin.
        $this->selectParentId = 'parent_id';
        //下拉列表查询第一层数据列表条件，如[['parent_id','=',0]],当表格为treeTable的时候，意味着你要输出的数据也会是树形的，这个时候首次查询最父层的数据列表可能需要传入这个参数，如果有配置了$this->SelectRelationWithJoins，这里就需要注意了，排序字段需要带上表名加一个点，如admin.
        $this->selectOneParentWhere = [];
        //下拉列表查询排序，如果有配置了$this->selectRelationWithJoins，这里就需要注意了，排序字段需要带上表名加一个点，如admin.
        $this->selectOrder = '';
        //列表排序，如果有配置了$this->relationWithJoins，这里就需要注意了，排序字段需要带上表名加一个点，如admin.
        $this->sort = 'id desc';
        //父id字段名称，如parent_id,当表格为treeTable的时候，意味着你要输出的数据也会是树形的，这个时候需要指定父级字段名称，如果有配置了$this->selectRelationWithJoins，这里就需要注意了，排序字段需要带上表名加一个点，如admin.，根据实际需求修改
        $this->parentField = '';
        //查询第一层数据列表条件，如[['parent_id','=',0]],当表格为treeTable的时候，意味着你要输出的数据也会是树形的，这个时候首次查询最父层的数据列表可能需要传入这个参数，如果有配置了$this->relationWithJoins，这里就需要注意了，排序字段需要带上表名加一个点，如admin.
        $this->oneParentWhere = [];
        //表格类型,table,treeTable
        $this->tableType = 'table';
        //树形表格分组字段，比如name，那么展开和搜索箭头就会在name这一列显示，当表格为treeTable的时候会用到
        $this->treeTableGroupField = '';
        //需要合计的字段，如['显示在哪个字段','显示哪个字段的值']，如果有配置了$this->selectRelationWithJoins，这里就需要注意了，排序字段需要带上表名加一个点，如['id'=>'admin.sex','money'=>admin.money']
        $this->totalRow = [];
        //设置主键
        $this->pk = 'id';
    }

    /**
     * 设置当前页面
     * @Author   July
     * @DateTime 2024-01-13T19:41:56+0800
     * @param    $table 表格
     */
    protected function buildPage(&$table = [])
    {
        //表格工具栏
        $table->getToolbar()
            ->addBtn(true, '添加', '98%', '98%')
            ->deleteBtn()
            ->refreshBtn();

        //表格数据
        $table->showCheckbox();
        $table->show('id', 'ID')->sort(true)->width(100);
        $table->show('config_name', '配置名称');
        $table->show('config_key', '配置键');
        $table->show('config_file', '配置文件路径');
        $table->show('create_time', '创建时间')->width(170)->sort(true);
        $table->show('update_time', '更新时间')->width(170)->sort(true);

        //表格右侧操作列
        $table->showRowHandleMenus()->width(130);
        $table->getTableRowBtns()
            ->editBtn(true, '编辑', '98%', '98%')
            ->viewBtn(true, '详情', '98%', '98%')
            ->deleteBtn();

    }

    /**
     * 处理数据
     * 因为查询出来的数据可能需要二次处理
     * @Author   July
     * @DateTime 2024-01-13T19:44:46+0800
     * @param  array   &$data 查询出来的数据
     */
    protected function handleData(&$data = [])
    {

    }

    /**
     * 处理查询条件
     * @Author   July
     * @DateTime 2023-11-16T20:45:54+0800
     * @param array $search  查询条件
     * @return  array $where
     */
    protected function filterWhere($search = [])
    {
        $where = [];
        foreach ($search as $k => $v) {
            if ($v === "") {
                continue;
            }
            switch ($k) {
                case "config_name":
                    $where[] = ['config_name', 'like', '%' . $v . '%'];
                    break;
            }
        }

        return $where;
    }

    /**
     * 处理下拉列表查询条件
     * @Author   July
     * @DateTime 2024-01-13T19:47:05+0800
     * @param  array $where  现有的查询条件
     * @return array
     */
    protected function filterSelectPageWhere($where = [])
    {

        return $where;
    }

    /**
     * 处理合计行信息
     * @Author   July
     * @DateTime 2023-11-16T20:45:54+0800
     * @param    array                   $where    已经处理过的最终查询条件，可以自己覆盖，用来自己重新查询数据
     * @param    integer                 $limit    每页多少条
     * @param    string                  $sort     排序
     * @param    integer                 $page     第几页
     * @param    array                   $totalRow 已经查询出来的合计信息，可以自己覆盖返回
     * @return   array                   $totalRow 将处理过的最终信息返回
     */
    protected function filterTotalRow($where = [], $limit = 20, $sort = '', $page = 1, $totalRow = [])
    {
        return $totalRow;
    }

    /**
     * @Author   July
     * @DateTime 2024-01-13T19:49:03+0800
     * @param    Object                   &$form  form对象
     * @param    integer                  $isEdit 是否是编辑：0否，1是
     * @param    array                    &$data  当前这条数据的内容
     */
    protected function buildForm(&$form, $isEdit, &$data = [])
    {
        if ($isEdit) {
            $form->tabs('config')->addTab('基础信息', 'base', true)->addTab('配置信息', 'config', false);
            $form->tabStart();
            $form->tabItemStart('base');
        }
        $form->show('text', 'config_name', '配置名称')->required();
        $form->show('text', 'config_key', '配置键')->required()->help('配置key值，取配置的时候用的就是这个key，如：sms_config');
        $form->show('text', 'config_file', '配置文件路径')->required()->help('配置文件路径：如：webconfig/System.php');

        $demo = <<<EOT
<pre>
    &lt?php
    //配置模板，注意，可以增加修改配置键，不要直接修改此文件配置值,里面的值只是默认值，真实值保存在数据库
    return [
        //后台标题名称
        'admin_name'      => '后台管理系统',
        //后台菜单顶部logo类型，0图片，1文字
        'admin_logo_type' => 0,
        //后台菜单顶部logo
        'admin_logo'      => '',
        //后台菜单顶部logo文字
        'admin_logo_text' => '',
        '__config__'      => function (\july\julyadmin\builder\Form &\$form, \$data) {
            \$form->show('text','admin_name', '后台名称');
            \$form->show('select','admin_logo_type', '后台菜单顶部logo类型')->options([0 => '图片', 1 => '文字']);
            \$form->show('text','admin_logo', '后台菜单顶部logo');
            \$form->show('text','admin_logo_text', '后台菜单顶部logo文字');
        },
    ];
    //获取方式
    //\july\julyadmin\common\model\Config::config('System');
</pre>

EOT;
        $form->show('html', 'demo', '配置demo')->default($demo);

        if ($isEdit) {
            $form->show('html', 'create_time', '创建时间');
            $form->show('html', 'update_time', '更新时间');
            $form->tabItemEnd();
        }

        if ($isEdit) {
            $rootPath = app()->getRootPath();
            $filePath = $rootPath . str_replace(['\\', '/'], DIRECTORY_SEPARATOR, $data['config_file']);
            if (!is_file($filePath)) {
                $this->error('原始配置文件不存在：' . $data['config_file']);
            }
            $default = include $filePath;

            $form->tabItemStart('config');
            $forms       = $this->getConfigForm($default, $data->toArray());
            $form->forms = array_merge($form->forms, $forms);
            $form->tabItemEnd();
            $form->tabEnd();
        }
    }

    /**
     * 获取配置表单信息
     * @return array
     */
    protected function getConfigForm($default, $data)
    {
        $__config__ = [];
        if (isset($default['__config__'])) {
            $__config__ = $default['__config__'] ?: [];
        }
        foreach ($default as $key => $val) {
            if ($key == '__config__') {
                continue;
            }
            $data[$key] = is_array($default[$key]) ? implode(',', $default[$key]) : $default[$key];
        }

        if (isset($data["config"]) && $data["config"]) {
            $config = json_decode($data["config"], true);
            foreach ($default as $key => $val) {
                if ($key == '__config__') {
                    continue;
                }
                if (isset($config[$key])) {
                    $data[$key] = is_array($config[$key]) ? implode(',', $config[$key]) : $config[$key];
                } else if (isset($default[$key])) {
                    $data[$key] = is_array($default[$key]) ? implode(',', $default[$key]) : $default[$key];
                } else {
                    $data[$key] = '';
                }
            }
        }
        $builder      = $this->builder();
        $form         = new Form($builder);
        $form->isEdit = 1;
        if (request()->action() == 'view') {
            $form->isView = true;
        }
        $form->data = $data;
        $__config__($form, $data);
        return $form->forms;
    }

    /**
     * 保存
     * @Author   July
     * @DateTime 2023-11-16T20:45:54+0800
     * @param  integer $isEdit 是否是编辑 0否，1是
     */
    protected function save($isEdit)
    {
        $pk = input("get." . $this->getPk());

        $data = input('post.');

        $rootPath = app()->getRootPath();
        $filePath = $rootPath . str_replace(['\\', '/'], DIRECTORY_SEPARATOR, $data['config_file']);
        if (!is_file($filePath)) {
            $this->error('原始配置文件不存在：' . $data['config_file']);
        }
        $default = include $filePath;

        //获取配置文件的所有key和默认值
        $values     = [];
        $__config__ = [];
        if (isset($default['__config__'])) {
            $__config__ = $default['__config__'] ?: [];
        }
        foreach ($default as $key => $val) {
            if ($key == '__config__') {
                continue;
            }
            $values[$key] = is_array($default[$key]) ? implode(',', $default[$key]) : $default[$key];
        }

        if ($isEdit) {
            foreach ($default as $key => $val) {
                if ($key == '__config__') {
                    continue;
                }
                if (isset($data[$key])) {
                    $values[$key] = is_array($data[$key]) ? implode(',', $data[$key]) : $data[$key];
                }
            }
        }
        $builder      = $this->builder();
        $form         = new Form($builder);
        $form->isEdit = $isEdit;
        $__config__($form, $values);
        $data["config"] = json_encode($data, JSON_UNESCAPED_UNICODE);
        cache('web_config_' . $data['config_key'], null);
        return $this->doSave($isEdit, $data, $pk);
    }
}
